package com.ruoyi.ai.service;

import com.ruoyi.ai.service.ChatService;
import com.ruoyi.ai.tools.ChatTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.model.tool.ToolCallingChatOptions;
import org.springframework.ai.model.tool.ToolCallingManager;
import org.springframework.ai.model.tool.ToolExecutionResult;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.method.MethodToolCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
import reactor.core.publisher.Flux;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author coach tam
 * @email 327395128@qq.com
 * @values 坚持灵活 灵活坚持
 * @since 2025/3/22
 */
@Slf4j
@Service
public class ChatServiceImpl implements ChatService {

    public static final String PROMPT = """
            你是一个雅橙科技教学助手，由龙哥研制，正在回答用户的提问。
            所有的回答都只能通过中文回答。
            所有回答的格式都是纯文本格式。
            我们公司的口号是"用心做教育"，你只能回答编程问题以及教学相关的业务，。
            使用来自“文档”部分的信息来提供准确的答案,尽可能保留原“文档”的内容。如果不确定或在“文档”部分找不到答案，只需表明你不知道答案即可。
            历史对话：
            {history}
            
            文档:
            {documents}
            
            问题
            {input}
            
            """;
    @Autowired
    private OpenAiChatModel chatModel;


    @Autowired
    private ChatTools chatTools;

    @Autowired
    private VectorService vectorService;

    // 配置 ChatMemory
    private ChatMemory chatMemory = new InMemoryChatMemory();

    @Override
    public Flux<ChatResponse> chatWithTools(String message) {

        return Flux.deferContextual(ctx -> {
            ToolCallingManager toolCallingManager = ToolCallingManager.builder().build();

            // 创建工具回调集合
            ToolCallback[] toolCallbacksSet = {
                    createToolCallback(chatTools, "getCurrentDateTime", "获取用户当前的日期信息"),
                    createToolCallback(chatTools, "queryTeachingPlan", "查询课表"),
                    createToolCallback(chatTools, "route", "跳转页面"),
                    createToolCallback(chatTools, "queryAssistantName", "查询助手信息"),
                    createToolCallback(chatTools, "queryUserName", "查询用户信息和学习情况"),
                    createToolCallback(chatTools, "queryCourse", "查询课程信息")
            };

            // 构建聊天选项
            ChatOptions chatOptions = ToolCallingChatOptions.builder()
                    .toolCallbacks(toolCallbacksSet)
                    .internalToolExecutionEnabled(false)
                    .maxTokens(200)
                    .frequencyPenalty(1.5)
                    .temperature(0.75)
                    .build();

            // 创建提示模板
            PromptTemplate promptTemplate = new PromptTemplate(PROMPT);
            String userId = ctx.get("userId");
            // 获取历史对话
            List<Message> historyMessages = chatMemory.get(userId, 10);

            // 获取当本地知识库文档
            List<String> contentList = vectorService.searchQuestion(message);
            // 构建提示并发送请求
            Map<String, Object> promptParams = Map.of(
                    "input", message,
                    "history", historyMessages,
                    "documents", contentList
            );
            Prompt prompt = promptTemplate.create(promptParams, chatOptions);

            ChatResponse chatResponse = chatModel.call(prompt);

            // 处理工具调用
            while (chatResponse.hasToolCalls()) {
                ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(prompt, chatResponse);
                prompt = new Prompt(toolExecutionResult.conversationHistory(), chatOptions);
                chatResponse = chatModel.call(prompt);
            }
            StringBuilder sb = new StringBuilder();
            return chatModel.stream(prompt)
                    .doOnNext(cr -> {
                        //追加响应
                        sb.append(cr.getResults().get(0).getOutput().getText());
                    }).doOnComplete(() -> {
                        //更新历史记录
                        chatMemory.add(userId, new UserMessage(message));
                        chatMemory.add(userId, new AssistantMessage(sb.toString()));
                    });
        });


    }


    /**
     * 创建工具回调
     *
     * @param toolObject  工具对象
     * @param methodName  方法名
     * @param description 描述
     * @return 工具回调
     */
    private ToolCallback createToolCallback(Object toolObject, String methodName, String description) {
        Method method = ReflectionUtils.findMethod(toolObject.getClass(), methodName);
        return MethodToolCallback.builder()
                .toolDefinition(ToolDefinition.builder(method).description(description).build())
                .toolMethod(method)
                .toolObject(toolObject)
                .build();
    }
}
